﻿//============== 시스템 네임스페이스
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
//=============== 개발자 네임스페이스
using DBF_ReadWrite;
using VectorAnalys;


namespace OpenShape
{
    #region 델리게이트 선언
    
    public delegate void Deligate_VisibleChanged(bool VisbleState, int id);  //델리게이트 선언 TOC를 통한 레이어 온/오프
    public delegate void Deligate_LayerColorChanged(Color penColor, Color brushColor, float penThickness, int id);  //델리게이트 선언 TOC를 통한 레이어 색상 및 두께 변경
    public delegate void Deligate_Form_ID(int id);  //델리게이트 선언 TOC를 통한 Form으로 ID전달 (레이어 전체보기, 레이어 선택)
    public delegate void Deligate_Form_None();  //델리게이트 선언 TOC를 통한 Form으로 전달값은 없음 (레이어 전체 온/오프)
    public delegate void Deligate_LabelShow(bool VisbleState, int id); //델리게이트 선언 TOC를 통한 레이어 라벨 온/오프
    public delegate void Deligate_ChangedLabelsProp(Font p_fonts, Color p_FontColor, bool p_showLabelChk, int ID, string p_FieldName);
    public delegate void Deligate_Identify(object pSelectFeatureID, PointF SelectLoc);  // 델리게이트 선언 객체선택용
    public delegate void Deligate_IdentifyType(int pFeatureSelectType);

    #endregion 

    public partial class GISViewer : Form
    {

        #region 기본변수 설정

        charF fchar = new charF();
        // LayerManager LayerManager = new LayerManager(); // 레이어 관리자
        Scaler m_scaler = new Scaler(); // 레이어 좌표 변환용
        VectorAnalysis  pVectorAnalysis = new VectorAnalysis();
        DBF_FileReadWriter DBf_FileRW = new DBF_FileReadWriter(); 

        bool m_isOpenSHP; // 레이어 추가상태

        //지도상에서 레이어 줌인, 줌아웃, 팬용 변수
        Point s_Pt = new Point();
        Point e_Pt = new Point();
        bool zoom_status = false;
        bool pan_status = false;
        Rectangle SelectRect = new Rectangle();

        // 레이어 그래픽 생성용 (더블버퍼링용)
        Graphics g2;
        private Bitmap nowLayerBitMap;

        // TOC의 요소 드래그용 변수
        public bool dragstats;
        Point origin_DragPt;
        int dragID;

        // 추가 폼 정의
        frmIdentify pfrmIdentify = new frmIdentify(); // 속성확인 창

        // 개체선택 타입 정의
        int FeatureSelectType = 0;

        #endregion


        // 델리게이트 이벤트
        public event Deligate_Identify GISViewer_EventIdentify;

        public GISViewer()
        {
            InitializeComponent();
        }

        private void GISViewer_Load(object sender, EventArgs e)
        {
            //버젼 정보 표시
            OperatingSystem os = Environment.OSVersion;
            Version OSver = os.Version;  // OS 버전 정보
            Version EnvVer = Environment.Version;
            Assembly myAsm = Assembly.Load("OpenShape");  // .Net 버전 정보
            AssemblyName aName = myAsm.GetName();
            Version AppVer = aName.Version;  // 프로그램 버전 정보
            this.Text = "GIS Viewer C#.Net (OS Ver. : " + Convert.ToString(OSver) + " / .Net Ver. : " + Convert.ToString(EnvVer) + "/ App Ver. : " + Convert.ToString(AppVer) + ")";

            split.SplitterDistance = 200;
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); //더블버퍼링

            // 레이어 이미지 저장용. 레이어는 전부 g2를 이용하여 그림.
            Graphics canvas = Map.CreateGraphics();
            nowLayerBitMap = new Bitmap(Map.Width, Map.Height, canvas);
            g2 = Graphics.FromImage(nowLayerBitMap);
            g2.Clear(Color.White);

            // 화면의 모서리 2점
            m_scaler.sxMin = 0;
            m_scaler.sxMax = Map.Right;
            m_scaler.syMin = 0;
            m_scaler.syMax = Map.Bottom;

            // 화면의 원점 
            m_scaler.sox = (m_scaler.sxMax + m_scaler.sxMin) / 2;
            m_scaler.soy = (m_scaler.syMax + m_scaler.syMin) / 2;

            // 지도의 모서리 2점 : 초기값으로 화면과 동일하게 설정
            m_scaler.mxMin = 0;
            m_scaler.mxMax = Map.Right;
            m_scaler.myMin = 0;
            m_scaler.myMax = Map.Bottom;

            // 지도의 원점 
            m_scaler.mox = (m_scaler.mxMax + m_scaler.mxMin) / 2;
            m_scaler.moy = (m_scaler.myMax + m_scaler.myMin) / 2;

         
            GISViewer_EventIdentify += new Deligate_Identify(pfrmIdentify.FeatureInfoShow);
            pfrmIdentify.frmIdentifyTypeChanged += new Deligate_IdentifyType(GISViewer_IdentyTypeChanged);

            //

        
        }

        private void GISViewer_IdentyTypeChanged(int pFeatureSelectType)
        {
            FeatureSelectType = pFeatureSelectType;
        }

        #region     TOC와의 델리게이트 함수 시작

        // 델리게이트 함수 시작
        private void GISViewer_VisibleChanged(bool st, int id)
        {
            if (split.Panel1.Controls.Count == LayerManager.m_Layers.Count)
            {
                LayerManager.m_Layers[id].m_isOn = st;

                g2.Clear(Color.White);
                this.Cursor = Cursors.WaitCursor;
                LayerManager.DrawLayers(g2, m_scaler);
                Map.Invalidate();
                this.Cursor = Cursors.Default;
            }
        }

        private void GISViewer_LayerColorChanged(Color penColor, Color brushColor, float penThickness, int id)
        {
            if (split.Panel1.Controls.Count == LayerManager.m_Layers.Count)
            {
                LayerManager.m_Layers[id].m_DrawProperties.penColor = penColor;
                LayerManager.m_Layers[id].m_DrawProperties.brushColor = brushColor;
                LayerManager.m_Layers[id].m_DrawProperties.penThickness = penThickness;

                g2.Clear(Color.White);
                this.Cursor = Cursors.WaitCursor;
                LayerManager.DrawLayers(g2, m_scaler);
                Map.Invalidate();
                this.Cursor = Cursors.Default;
            }
        }

        private void GISViewer_sLayerFullExtent(int id)
        {
            m_scaler.mxMin = LayerManager.m_Layers[id].m_MBR.xmin;
            m_scaler.myMin = LayerManager.m_Layers[id].m_MBR.ymin;
            m_scaler.mxMax = LayerManager.m_Layers[id].m_MBR.xmax;
            m_scaler.myMax = LayerManager.m_Layers[id].m_MBR.ymax;
            m_scaler.mox = (m_scaler.mxMax + m_scaler.mxMin) / 2;
            m_scaler.moy = (m_scaler.myMax + m_scaler.myMin) / 2;

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        private void GISViewer_isLayerSelected(int id)
        {
            for (int i = 0; i < LayerManager.m_Layers.Count; i++)
            {
                Toc_Layer toc_element = split.Panel1.Controls[i] as Toc_Layer;
                if (i == id)
                {
                    toc_element.isLSelected = true;
                    toc_element.l_Name.BackColor = Color.FromArgb(117, 186, 255);
                    LayerManager.m_Layers[i].m_isSelect = true;
                }
                else
                {
                    toc_element.isLSelected = false;
                    toc_element.l_Name.BackColor = Color.White;
                    LayerManager.m_Layers[i].m_isSelect = false;
                }
            }
        }

        private void GISViewer_Refresh()
        {
            // TOC에 레이어 요소의 위치 설정
            for (int i = split.Panel1.Controls.Count - 1; i >= 0; i--)
            {
                Toc_Layer tcNow = split.Panel1.Controls[i] as Toc_Layer;
                if (i == split.Panel1.Controls.Count - 1)
                {
                    tcNow.Top = 0;
                }
                else
                {
                    Toc_Layer tcPre = split.Panel1.Controls[i + 1] as Toc_Layer;
                    tcNow.Top = tcPre.Top + tcPre.Height + 4;
                }
            }
        }

        private void GISViewer_LayerRemove(int id)
        {
            this.Cursor = Cursors.WaitCursor;
            LayerManager.RemoveLayer(id);
            move_TocElement();
            this.Cursor = Cursors.Default;
        }

        private void GISViewer_LabelShow(bool st, int id)
        {
            if (split.Panel1.Controls.Count == LayerManager.m_Layers.Count)
            {
                LayerManager.m_Layers[id].m_isLabelOn = st;
                LayerManager.m_Layers[id].m_DBF = DBf_FileRW.Reader(LayerManager.m_Layers[id].m_DataSourceName);
                g2.Clear(Color.White);
                this.Cursor = Cursors.WaitCursor;
                LayerManager.DrawLayers(g2, m_scaler);
                Map.Invalidate();
                this.Cursor = Cursors.Default;
            }
        }

        private void GISViewer_ChangedLabelsProp(Font pFont, Color pFontColor, bool p_showLabelChk, int id, string m_Fname)
        {
            LayerManager.m_Layers[id].fonts = pFont;
            LayerManager.m_Layers[id].pFontColor = pFontColor;
            LayerManager.m_Layers[id].m_isLabelOn = p_showLabelChk;
            LayerManager.m_Layers[id].m_FieldName = m_Fname;

            //DBF_Module dbm = new DBF_Module();
            //dbm.DBF_Loader(id);
            LayerManager.m_Layers[id].m_DBF = DBf_FileRW.Reader(LayerManager.m_Layers[id].m_DataSourceName);
            g2.Clear(Color.White);
            this.Cursor = Cursors.WaitCursor;
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
            this.Cursor = Cursors.Default;
        }

        #endregion

        #region 레이어 불러오기 및 그리기, 재생성용

        private void Map_Paint(object sender, PaintEventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            Graphics g = e.Graphics;

            if ((LayerManager.m_Layers.Count != 0))
            {
                g.DrawImage(nowLayerBitMap, 0, 0);
            }
            if (((ZoomIn.Checked == true) && (zoom_status == true)) || ((ZoomOut.Checked == true) && (zoom_status == true)))
            {
                Draw_Select_Rect(g, Color.Blue);
            }
            if (pan_status == true)
            //if ((Pannig.Checked == true) && (pan_status == true))
            {
                g.Clear(Color.White);
                g.DrawImage(nowLayerBitMap, 0 - (s_Pt.X - e_Pt.X), 0 - (s_Pt.Y - e_Pt.Y));
            }
            this.Cursor = Cursors.Default;
        }

        private void addData_Click(object sender, EventArgs e)
        {
            bool load_state;
            load_state = OnShpopen();

            if (load_state == true)
            {
                //메뉴 활성화
                통계분석ToolStripMenuItem.Enabled = true;

                //TOC에 레이어 요소의 델리게이트 선언

                Toc_Layer toc_element = new Toc_Layer();

                toc_element.Toc_Visble += new Deligate_VisibleChanged(GISViewer_VisibleChanged);  //델리게이트 (레이어 온/오프)
                toc_element.Toc_LayerColorChanged += new Deligate_LayerColorChanged(GISViewer_LayerColorChanged);  //델리게이트 (레이어 색상 및 선두께)
                toc_element.TOC_layerfullextent += new Deligate_Form_ID(GISViewer_sLayerFullExtent);  // 델리게이트  (선택 레이어 전체 보기)
                toc_element.TOC_isLayerSelected += new Deligate_Form_ID(GISViewer_isLayerSelected);  // 델리게이트 (선택레이어 변경)
                toc_element.Toc_Refresh += new Deligate_Form_None(GISViewer_Refresh);  // 델리게이트 (TOC재생성, Panel1 재생성)
                toc_element.Toc_LayerRemove += new Deligate_Form_ID(GISViewer_LayerRemove);  // 델리게이트 (레이어 삭제)
                toc_element.Toc_LabelShow += new Deligate_LabelShow(GISViewer_LabelShow);  // 델리게이트 (레이어 라벨 온/오프)
                toc_element.TOC_ChangedLabelsProp += new Deligate_ChangedLabelsProp(GISViewer_ChangedLabelsProp);

                toc_element.MouseDown += new MouseEventHandler(split_Panel1_MouseDown);
                toc_element.MouseMove += new MouseEventHandler(split_Panel1_MouseMove);
                toc_element.MouseUp += new MouseEventHandler(split_Panel1_MouseUp);

                // TOC에 레이어 요소의 기본값 설정
                if (LayerManager.m_Layers.Count == 1)
                {
                    toc_element.isLSelected = LayerManager.m_Layers[0].m_isSelect = true;
                    toc_element.l_Name.BackColor = Color.FromArgb(117, 186, 255);
                }

                toc_element.TOC_DataSourceName = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DataSourceName;
                string[] entries;
                entries = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DataSourceName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string entry in entries)
                {
                    toc_element.l_Name.Text = entry;
                }
                
                toc_element.l_Visible.Checked = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_isOn;
                toc_element.brushColor = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DrawProperties.brushColor;
                toc_element.penColor = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DrawProperties.penColor;
                toc_element.penThickness = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DrawProperties.penThickness;
                toc_element.shape_type = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_nShapeType;
                toc_element.isID = LayerManager.m_Layers.Count - 1;
                toc_element.fonts = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].fonts;
                toc_element.pFontColor = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].pFontColor;

                // TOC에 레이어 요소 추가
                split.Panel1.Controls.Add(toc_element);

                // TOC에 레이어 요소의 위치 설정
                for (int i = split.Panel1.Controls.Count-1; i >=0; i--)
                {
                    Toc_Layer tcNow = split.Panel1.Controls[i] as Toc_Layer;
                    if (i == split.Panel1.Controls.Count - 1)
                    {
                        tcNow.Top = 0;
                    }
                    else
                    {
                        Toc_Layer tcPre = split.Panel1.Controls[i+1] as Toc_Layer;
                        tcNow.Top = tcPre.Top + tcPre.Height + 4;
                    }
                }
            }
        }


        private bool OnShpopen()
        {
            OpenFileDialog oFD1 = new OpenFileDialog();

            
            oFD1.Filter = "SHP files (*.shp)|*.shp|All files (*.*)|*.*";
            oFD1.FilterIndex = 1;
            oFD1.RestoreDirectory = true;

            if (oFD1.ShowDialog() == DialogResult.OK)
            {
                if ((oFD1.OpenFile()) != null)
                {
                    this.Cursor = Cursors.WaitCursor;
                    LayerManager.AddLayer(oFD1.FileName, "shp");
                    this.Cursor = Cursors.Default;
                    /////////////////////////////////
                    // 첫 레이어에 대해서 지도 영역 크기 셋팅
                    if (m_isOpenSHP == false)
                    {
                        m_scaler.mxMin = LayerManager.m_Layers[0].m_MBR.xmin;
                        m_scaler.myMin = LayerManager.m_Layers[0].m_MBR.ymin;
                        m_scaler.mxMax = LayerManager.m_Layers[0].m_MBR.xmax;
                        m_scaler.myMax = LayerManager.m_Layers[0].m_MBR.ymax;
                        m_scaler.mox = (m_scaler.mxMax + m_scaler.mxMin) / 2;
                        m_scaler.moy = (m_scaler.myMax + m_scaler.myMin) / 2;

                    }
                    //Graphics g = split.Panel2.CreateGraphics();
                    //LayerManager.DrawLayers(g, m_scaler);
                    
                    ZoomIn.Enabled = true;
                    ZoomOut.Enabled = true;
                    FixZoomIn.Enabled = true;
                    FixZoomOut.Enabled = true;
                    Pannig.Enabled = true;
                    FullExtent.Enabled = true;
                    SelectFeature.Enabled = true;
                    Identify.Enabled = true;
                    Draw_layer();
                    m_isOpenSHP = true;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private void Draw_layer()
        {
            this.Cursor = Cursors.WaitCursor;

            Graphics canvas = Map.CreateGraphics();
            nowLayerBitMap = new Bitmap(Map.Width, Map.Height, canvas);
            g2 = Graphics.FromImage(nowLayerBitMap);
            g2.Clear(Color.White);

            LayerManager.DrawLayers(g2, m_scaler);

            Map.Invalidate();
            this.Cursor = Cursors.Default;
        }

        #endregion

        #region Split.Panel1 레이어 이동용 마우스 이벤트

        private void split_Panel1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                for (int i = 0; i < split.Panel1.Controls.Count; i++)
                {
                    Toc_Layer temp_Panel = split.Panel1.Controls[i] as Toc_Layer;
                    if ((sender == temp_Panel) && (dragstats == false))
                    {
                        origin_DragPt.X = e.X;
                        origin_DragPt.Y = e.Y;
                        dragstats = true;
                        dragID = i;
                    }
                }
            }
        }

        private void split_Panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (dragstats == true)
            {
                Graphics g = split.Panel1.CreateGraphics();
                int OutID, OutY, move_Y;
                Toc_Layer temp_Panel = split.Panel1.Controls[dragID] as Toc_Layer;

                move_Y = temp_Panel.Top;

                if (dragID == split.Panel1.Controls.Count - 1)
                {
                    if ((e.Y - origin_DragPt.Y) < 0)
                    {
                        this.Cursor = Cursors.No;
                    }
                    else
                    {
                        this.Cursor = Cursors.Default;
                        move_Y += (e.Y - origin_DragPt.Y);
                        drag_element(dragID, new Point(e.X, e.Y), e.Y - origin_DragPt.Y, move_Y, out OutID, out OutY);
                        g.Clear(Color.White);
                        g.DrawLine(new Pen(Color.Aquamarine, 3f), 0, OutY, split.Panel1.Width, OutY);
                    }
                }
                else if (dragID == 0)
                {
                    if ((e.Y - origin_DragPt.Y) > 0)
                    {
                        this.Cursor = Cursors.No;
                    }
                    else
                    {
                        this.Cursor = Cursors.Default;
                        move_Y += (e.Y - origin_DragPt.Y);
                        drag_element(dragID, new Point(e.X, e.Y), e.Y - origin_DragPt.Y, move_Y, out OutID, out OutY);
                        g.Clear(Color.White);
                        g.DrawLine(new Pen(Color.Aquamarine, 3f), 0, OutY, split.Panel1.Width, OutY);
                    }
                }
                else
                {
                    move_Y += (e.Y - origin_DragPt.Y);
                    drag_element(dragID, new Point(e.X, e.Y), e.Y - origin_DragPt.Y, move_Y, out OutID, out OutY);
                    g.Clear(Color.White);
                    g.DrawLine(new Pen(Color.Aquamarine, 3f), 0, OutY, split.Panel1.Width, OutY);
                }
            }
        }

        private void split_Panel1_MouseUp(object sender, MouseEventArgs e)
        {
            if (dragstats == true)
            {
                Graphics g = split.Panel1.CreateGraphics();
                g.Clear(Color.White);
                dragstats = false;
                int OutID, OutY, move_Y;

                Toc_Layer temp_Panel = split.Panel1.Controls[dragID] as Toc_Layer;
                move_Y = temp_Panel.Top;

                move_Y += (e.Y - origin_DragPt.Y);
                drag_element(dragID, new Point(e.X, e.Y), e.Y - origin_DragPt.Y, move_Y, out OutID, out OutY);
                LayerManager.MoveLayer(dragID, OutID);
                move_TocElement();
                this.Cursor = Cursors.Default;
            }
        }

        private void drag_element(int id, Point Now_Pt, int diffet_y, int move_y, out int OutID, out int OutY)
        {
            int[] element_TopY = new int[split.Panel1.Controls.Count];
            int[] element_BottomY = new int[split.Panel1.Controls.Count];
            OutID = id;
            OutY = move_y;

            for (int i = 0; i < split.Panel1.Controls.Count; i++)
            {
                Toc_Layer temp_Panel = split.Panel1.Controls[i] as Toc_Layer;
                element_TopY[i] = temp_Panel.Top;
                element_BottomY[i] = temp_Panel.Bottom;
            }

            if (diffet_y > 0) // 아래로 이동, element_BottomY과 비교
            {
                for (int i = id - 1; i >= 0; i--)
                {
                    if (element_BottomY[i] < move_y)
                    {
                        OutID = i;
                        OutY = element_BottomY[i];
                    }
                }
            }

            if (diffet_y < 0) // 위로 이동, element_TopY고 비교
            {
                for (int i = id + 1; i < split.Panel1.Controls.Count; i++)
                {
                    if (element_TopY[i] > move_y)
                    {
                        OutID = i;
                        OutY = element_TopY[i];
                    }
                }
            }

            if (OutY == move_y)
            {
                OutID = id;
                OutY = element_TopY[id];
            }
        }

        private void move_TocElement()
        {
            split.Panel1.Controls.Clear();
            for (int i = 0; i < LayerManager.m_Layers.Count; i++)
            {
                //TOC에 레이어 요소의 델리게이트 선언
                Toc_Layer toc_element = new Toc_Layer();
                toc_element.Toc_Visble += new Deligate_VisibleChanged(GISViewer_VisibleChanged);  //델리게이트 (레이어 온/오프)
                toc_element.Toc_LayerColorChanged += new Deligate_LayerColorChanged(GISViewer_LayerColorChanged);  //델리게이트 (레이어 색상 및 선두께)
                toc_element.TOC_layerfullextent += new Deligate_Form_ID(GISViewer_sLayerFullExtent);  // 델리게이트  (선택 레이어 전체 보기)
                toc_element.TOC_isLayerSelected += new Deligate_Form_ID(GISViewer_isLayerSelected);  // 델리게이트 (선택레이어 변경)
                toc_element.Toc_Refresh += new Deligate_Form_None(GISViewer_Refresh);  // 델리게이트 (TOC재생성, Panel1 재생성)
                toc_element.Toc_LayerRemove += new Deligate_Form_ID(GISViewer_LayerRemove);  // 델리게이트 (레이어 삭제)

                toc_element.MouseDown += new MouseEventHandler(split_Panel1_MouseDown);
                toc_element.MouseMove += new MouseEventHandler(split_Panel1_MouseMove);
                toc_element.MouseUp += new MouseEventHandler(split_Panel1_MouseUp);

                // TOC에 레이어 요소의 기본값 설정
                if (i == 0)
                {
                    toc_element.isLSelected = LayerManager.m_Layers[0].m_isSelect = true;
                    toc_element.l_Name.BackColor = Color.FromArgb(117, 186, 255);
                }

                toc_element.TOC_DataSourceName = LayerManager.m_Layers[LayerManager.m_Layers.Count - 1].m_DataSourceName;
                string[] entries;
                entries = LayerManager.m_Layers[i].m_DataSourceName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string entry in entries)
                {
                    toc_element.l_Name.Text = entry;
                }

                toc_element.l_Visible.Checked = LayerManager.m_Layers[i].m_isOn;
                toc_element.brushColor = LayerManager.m_Layers[i].m_DrawProperties.brushColor;
                toc_element.penColor = LayerManager.m_Layers[i].m_DrawProperties.penColor;
                toc_element.penThickness = LayerManager.m_Layers[i].m_DrawProperties.penThickness;
                toc_element.shape_type = LayerManager.m_Layers[i].m_nShapeType;
                toc_element.isID = i;

                // TOC에 레이어 요소 추가
                split.Panel1.Controls.Add(toc_element);
            }
            GISViewer_Refresh();

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        #endregion

        #region Map 마우스 이벤트

        private void Map_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if ((ZoomIn.Checked == true) || (ZoomOut.Checked == true))
                {
                    zoom_status = true;
                    s_Pt = new Point(e.X, e.Y);
                    e_Pt = new Point(e.X, e.Y);
                }
                if (Pannig.Checked == true)
                {
                    pan_status = true;
                    s_Pt = new Point(e.X, e.Y);
                    e_Pt = new Point(e.X, e.Y);
                }
            }
            else if (e.Button == MouseButtons.Middle)
            {
                pan_status = true;
                Map.Cursor = Cursors.NoMove2D;
                s_Pt = new Point(e.X, e.Y);
                e_Pt = new Point(e.X, e.Y);
            }
        }

        private void Map_MouseMove(object sender, MouseEventArgs e)
        {
            // 맵상의 좌표 출력
            double mx, my;
            m_scaler.DeviceToWorld((double)e.X, (double)e.Y, out mx, out my);
            StatusPoint.Text = "X = " + Convert.ToString((float)mx) + ", Y = " + Convert.ToString((float)my);

            if (e.Button == MouseButtons.Left)
            {
                if ((ZoomIn.Checked == true) || (ZoomOut.Checked == true))
                {
                    e_Pt = new Point(e.X, e.Y);

                    GetRect();
                    Map.Invalidate();
                }
                if ((Pannig.Checked == true) && (pan_status == true))
                {
                    e_Pt = new Point(e.X, e.Y);
                    
                    Map.Invalidate();
                }
            }
            else if ((e.Button == MouseButtons.Middle) && (pan_status == true))
            {
                pan_status = true;
                e_Pt = new Point(e.X, e.Y);

                Map.Invalidate();
            }
        }


        private void Map_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if ((ZoomIn.Checked == true) && (zoom_status == true ))
                {
                    zoom_status = false;
                    e_Pt = new Point(e.X, e.Y);

                    if (s_Pt == e_Pt)
                    {
                        fZoomIn_Function(s_Pt);
                    }
                    else
                    {
                        GeoRect newMBR = new GeoRect();
                        double x1, x2, y1, y2;
                        m_scaler.DeviceToWorld((double)s_Pt.X, (double)s_Pt.Y, out x1, out y1);
                        m_scaler.DeviceToWorld((double)e_Pt.X, (double)e_Pt.Y, out x2, out y2);

                        if (x1 > x2)
                        {
                            newMBR.xmax = x1;
                            newMBR.xmin = x2;
                        }
                        else
                        {
                            newMBR.xmax = x2;
                            newMBR.xmin = x1;
                        }
                        if (y1 > y2)
                        {
                            newMBR.ymax = y1;
                            newMBR.ymin = y2;
                        }
                        else
                        {
                            newMBR.ymax = y2;
                            newMBR.ymin = y1;
                        }

                        if (((newMBR.xmax - newMBR.xmin) < 20) || ((newMBR.ymax - newMBR.ymin) < 20))
                        {
                            Map.Invalidate();
                            return;
                        }

                        m_scaler.mxMin = newMBR.xmin;
                        m_scaler.myMin = newMBR.ymin;
                        m_scaler.mxMax = newMBR.xmax;
                        m_scaler.myMax = newMBR.ymax;
                        m_scaler.mox = (m_scaler.mxMax + m_scaler.mxMin) / 2;
                        m_scaler.moy = (m_scaler.myMax + m_scaler.myMin) / 2;

                        g2.Clear(Color.White);
                        LayerManager.DrawLayers(g2, m_scaler);
                        Map.Invalidate();
                    }
                }
                if (ZoomOut.Checked == true)
                {
                    zoom_status = false;
                    e_Pt = new Point(e.X, e.Y);


                    if (s_Pt == e_Pt)
                    {
                        fZoomOut_Function(s_Pt);
                    }
                    else
                    {
                        GeoRect newMBR = new GeoRect();
                        double x1, x2, y1, y2;
                        m_scaler.DeviceToWorld((double)s_Pt.X, (double)s_Pt.Y, out x1, out y1);
                        m_scaler.DeviceToWorld((double)e_Pt.X, (double)e_Pt.Y, out x2, out y2);

                        if (x1 > x2)
                        {
                            newMBR.xmax = x1;
                            newMBR.xmin = x2;
                        }
                        else
                        {
                            newMBR.xmax = x2;
                            newMBR.xmin = x1;
                        }
                        if (y1 > y2)
                        {
                            newMBR.ymax = y1;
                            newMBR.ymin = y2;
                        }
                        else
                        {
                            newMBR.ymax = y2;
                            newMBR.ymin = y1;
                        }

                        if (((newMBR.xmax - newMBR.xmin) < 20) || ((newMBR.ymax - newMBR.ymin) < 20))
                        {
                            Map.Invalidate();
                            return;
                        }

                        m_scaler.mxMin = m_scaler.mxMin - (newMBR.xmin - m_scaler.mxMin);
                        m_scaler.myMin = m_scaler.myMin - (newMBR.ymin - m_scaler.myMin);
                        m_scaler.mxMax = m_scaler.mxMax + (m_scaler.mxMax - newMBR.xmax);
                        m_scaler.myMax = m_scaler.myMax + (m_scaler.myMax - newMBR.ymax);
                        m_scaler.mox = (m_scaler.mxMax + m_scaler.mxMin) / 2;
                        m_scaler.moy = (m_scaler.myMax + m_scaler.myMin) / 2;

                        g2.Clear(Color.White);
                        LayerManager.DrawLayers(g2, m_scaler);
                        Map.Invalidate();
                    }
                }
                if ((Pannig.Checked == true) && (pan_status == true))
                {
                    pan_status = false;
                    Pannig_Fuction();
                    Map.Invalidate();
                }
                if (SelectFeature.Checked == true)
                {
                    //func_SelectFeature(new PointF(e.X, e.Y));
                }
                if ( Identify.Checked == true)
                {
                    List<SelectFeatureID> pSelectFeatureID = new List<SelectFeatureID>();
                    int TempLayerIndex = -1;

                     
                     switch (FeatureSelectType)
                     {
                         case 0:  // 선택된 레이어에서 객체 선택
                             for (int i = 0; i < LayerManager.m_Layers.Count; i++)
                             {
                                 if (LayerManager.m_Layers[i].m_isSelect == true)
                                 {
                                     TempLayerIndex = i;
                                 }
                             }
                             break;

                         case 1:  // 최상위 레이어에서 객체 선택
                             TempLayerIndex = LayerManager.m_Layers.Count-1;
                             break;

                         case 2:  // 전체 레이어에서 객체 선택
                             TempLayerIndex = -1;
                             break;                             
                     }

                    
                    pSelectFeatureID = pVectorAnalysis.func_SelectPolygonToPoint(new PointF(e.X, e.Y), TempLayerIndex, m_scaler);

                    double sx, sy;
                    m_scaler.DeviceToWorld(e.X, e.Y, out sx, out sy);

                    GISViewer_EventIdentify(pSelectFeatureID, new PointF((float)sx, (float)sy));
                }
            }
            else if ((e.Button == MouseButtons.Middle) && (pan_status == true))
            {
                pan_status = false;
                Map.Cursor = Cursors.Default;
                Pannig_Fuction();
                Map.Invalidate();
            }
            
        }

        

        private void Map_MouseEnter(object sender, EventArgs e)
        {
            if (Pannig.Checked == true)
            {
                Map.Cursor = Cursors.NoMove2D;
            }
            else
            {
                Map.Cursor = Cursors.Default;
            }
        }

        #endregion

        #region Map에서 작동할 줌인, 줌아웃, 팬, 선택영역 그리기용 함수

        private void Draw_Select_Rect(Graphics g, Color col)
        {
            Pen pPen = new Pen(col, 1.0f);
            g.DrawRectangle(pPen, SelectRect);
            pPen.Dispose();
        }

        private void GetRect()
        {
            int x, y;

            if (s_Pt.X <= e_Pt.X)
                x = s_Pt.X;
            else
                x = e_Pt.X;

            if (s_Pt.Y <= e_Pt.Y)
                y = s_Pt.Y;
            else
                y = e_Pt.Y;

            SelectRect = new Rectangle(x, y, (int)Math.Abs(e_Pt.X - s_Pt.X), (int)Math.Abs(e_Pt.Y - s_Pt.Y));
        }

        private void Pannig_Fuction()
        {
            double mx1, mx2, my1, my2;
            m_scaler.DeviceToWorld((double)s_Pt.X, (double)s_Pt.Y, out mx1, out my1);
            m_scaler.DeviceToWorld((double)e_Pt.X, (double)e_Pt.Y, out mx2, out my2);

            m_scaler.mox += (mx1 - mx2);
            m_scaler.moy += (my1 - my2);

            double mWidth = m_scaler.mxMax - m_scaler.mxMin;
            double mHeight = m_scaler.myMax - m_scaler.myMin;

            m_scaler.mxMin = m_scaler.mox - (mWidth / 2);
            m_scaler.mxMax = m_scaler.mox + (mWidth / 2);
            m_scaler.myMin = m_scaler.moy - (mHeight / 2);
            m_scaler.myMax = m_scaler.moy + (mHeight / 2);

            Graphics canvas = Map.CreateGraphics();
            nowLayerBitMap = new Bitmap(Map.Width, Map.Height, canvas);
            g2 = Graphics.FromImage(nowLayerBitMap);
            g2.Clear(Color.White);

            LayerManager.DrawLayers(g2, m_scaler);
        }

        private void fZoomIn_Function()
        {
            double mWidth, mHeight;

            mWidth = m_scaler.mxMax - m_scaler.mxMin;
            mHeight = m_scaler.myMax - m_scaler.myMin;

            mWidth *= 0.8;
            mHeight *= 0.8;

            m_scaler.mxMin = m_scaler.mox - mWidth / 2;
            m_scaler.mxMax = m_scaler.mox + mWidth / 2;
            m_scaler.myMin = m_scaler.moy - mHeight / 2;
            m_scaler.myMax = m_scaler.moy + mHeight / 2;

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        private void fZoomOut_Function()
        {
            double mWidth, mHeight;

            mWidth = m_scaler.mxMax - m_scaler.mxMin;
            mHeight = m_scaler.myMax - m_scaler.myMin;

            mWidth *= 1.2;
            mHeight *= 1.2;

            m_scaler.mxMin = m_scaler.mox - mWidth / 2;
            m_scaler.mxMax = m_scaler.mox + mWidth / 2;
            m_scaler.myMin = m_scaler.moy - mHeight / 2;
            m_scaler.myMax = m_scaler.moy + mHeight / 2;
            ;
            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        private void fZoomIn_Function(Point pt)
        {
            double mWidth, mHeight;

            mWidth = m_scaler.mxMax - m_scaler.mxMin;
            mHeight = m_scaler.myMax - m_scaler.myMin;

            mWidth *= 0.8;
            mHeight *= 0.8;

            m_scaler.DeviceToWorld((double)pt.X, (double)pt.Y, out m_scaler.mox, out m_scaler.moy);

            m_scaler.mxMin = m_scaler.mox - mWidth / 2;
            m_scaler.mxMax = m_scaler.mox + mWidth / 2;
            m_scaler.myMin = m_scaler.moy - mHeight / 2;
            m_scaler.myMax = m_scaler.moy + mHeight / 2;

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        private void fZoomOut_Function(Point pt)
        {
            double mWidth, mHeight;

            mWidth = m_scaler.mxMax - m_scaler.mxMin;
            mHeight = m_scaler.myMax - m_scaler.myMin;

            mWidth *= 1.2;
            mHeight *= 1.2;

            m_scaler.DeviceToWorld((double)pt.X, (double)pt.Y, out m_scaler.mox, out m_scaler.moy);

            m_scaler.mxMin = m_scaler.mox - mWidth / 2;
            m_scaler.mxMax = m_scaler.mox + mWidth / 2;
            m_scaler.myMin = m_scaler.moy - mHeight / 2;
            m_scaler.myMax = m_scaler.moy + mHeight / 2;

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }
        
        #endregion

        #region 메인 버튼메뉴 함수 시작

        private void GeneralPointer_Click(object sender, EventArgs e)
        {
            GeneralPointer.Checked = true;
            ZoomIn.Checked = false;
            ZoomOut.Checked = false;
            Pannig.Checked = false;
            SelectFeature.Checked = false;
            Identify.Checked = false;
        }

        private void ZoomIn_Click(object sender, EventArgs e)
        {
            GeneralPointer.Checked = false;
            ZoomIn.Checked = true;
            ZoomOut.Checked = false;
            Pannig.Checked = false;
            SelectFeature.Checked = false;
            Identify.Checked = false;
        }

        private void ZoomOut_Click(object sender, EventArgs e)
        {
            GeneralPointer.Checked = false;
            ZoomIn.Checked = false;
            ZoomOut.Checked = true;
            Pannig.Checked = false;
            SelectFeature.Checked = false;
            Identify.Checked = false;
        }

        private void Pannig_Click(object sender, EventArgs e)
        {
            GeneralPointer.Checked = false;
            ZoomIn.Checked = false;
            ZoomOut.Checked = false;
            Pannig.Checked = true;
            SelectFeature.Checked = false;
            Identify.Checked = false;
        }

        private void FullExtent_Click(object sender, EventArgs e)
        {
            GeoRect FullExtent = new GeoRect();

            FullExtent.xmin = LayerManager.m_Layers[0].m_MBR.xmin;
            FullExtent.xmax = LayerManager.m_Layers[0].m_MBR.xmax;
            FullExtent.ymin = LayerManager.m_Layers[0].m_MBR.ymin;
            FullExtent.ymax = LayerManager.m_Layers[0].m_MBR.ymax;

            for (int i = 1; i < LayerManager.m_Layers.Count; i++)
            {
                if (FullExtent.xmin > LayerManager.m_Layers[i].m_MBR.xmin)
                    FullExtent.xmin = LayerManager.m_Layers[i].m_MBR.xmin;
                if (FullExtent.xmax < LayerManager.m_Layers[i].m_MBR.xmax)
                    FullExtent.xmax = LayerManager.m_Layers[i].m_MBR.xmax;
                if (FullExtent.ymin > LayerManager.m_Layers[i].m_MBR.ymin)
                    FullExtent.ymin = LayerManager.m_Layers[i].m_MBR.ymin;
                if (FullExtent.ymax < LayerManager.m_Layers[i].m_MBR.ymax)
                    FullExtent.ymax = LayerManager.m_Layers[i].m_MBR.ymax;
            }
            m_scaler.mxMin = FullExtent.xmin;
            m_scaler.mxMax = FullExtent.xmax;
            m_scaler.myMin = FullExtent.ymin;
            m_scaler.myMax = FullExtent.ymax;
            m_scaler.sox = (m_scaler.sxMax + m_scaler.sxMin) / 2;
            m_scaler.soy = (m_scaler.syMax + m_scaler.syMin) / 2;

            g2.Clear(Color.White);
            LayerManager.DrawLayers(g2, m_scaler);
            Map.Invalidate();
        }

        private void FixZoomIn_Click(object sender, EventArgs e)
        {
            fZoomIn_Function();
        }

        private void FixZoomOut_Click(object sender, EventArgs e)
        {
            fZoomOut_Function();
        }
        private void SelectFeature_Click(object sender, EventArgs e)
        {
            GeneralPointer.Checked = false;
            ZoomIn.Checked = false;
            ZoomOut.Checked = false;
            Pannig.Checked = false;
            SelectFeature.Checked = true;
            Identify.Checked = false;
        }

        private void Identify_Click(object sender, EventArgs e)
        {

            GeneralPointer.Checked = false;
            ZoomIn.Checked = false;
            ZoomOut.Checked = false;
            Pannig.Checked = false;
            SelectFeature.Checked = false;
            Identify.Checked = true;

            pfrmIdentify.Show();

        }

        #endregion

        #region Map 의 이벤트

        private void Map_SizeChanged(object sender, EventArgs e)
        {
            if (split.SplitterDistance > 400)
            {
                split.SplitterDistance = 400;
            }
            else if (split.SplitterDistance < 200)
            {
                split.SplitterDistance = 200;
            }
            Map.Width = split.Panel2.Width - 22;
            Map.Height = split.Panel2.Height - 22;

            vScroll.Left = split.Panel2.Width - 22;
            vScroll.Height = split.Panel2.Height - 22;
            hScroll.Top = split.Panel2.Height - 22;
            hScroll.Width = split.Panel2.Width - 22;

            ///
            m_scaler.sxMax = Map.Width;
            m_scaler.syMax = Map.Height;
            

            Draw_layer();
        }
        #endregion

        #region 메뉴바 함수 시작

        private void m_Cluster_Click(object sender, EventArgs e) // 군집분석
        {
            int Index = -1;
            for (int i = 0; i < LayerManager.m_Layers.Count; i++)
            {
                if (LayerManager.m_Layers[i].m_isSelect == true)
                {
                    Index = i ;
                }
            }

            // module의 DBF_Module.cs에서 DBF로드, 데이터 읽음

            LayerManager.m_Layers[Index].m_DBF = DBf_FileRW.Reader(LayerManager.m_Layers[Index].m_DataSourceName);
            // Tool의 cluster.cs로 넘김고
            Cluster diagCluster = new Cluster(Index);
            diagCluster.Show();
            // Tool의 cluster.cs에서 분석
            // 트리분석구조(트리뷰써도됨) 나오면 좋고
            // DBF에서 읽어온 배열에 필드추가하고 그룹 번호 입력
        }

        #endregion


    }
}